package com.wanyang.filter;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.wanyang.bo.MemberBO;
import com.wanyang.config.IgnoreUrlsConfig;
import com.wanyang.exception.ApiException;
import com.wanyang.service.JwtTokenHelper;
import com.wanyang.service.MemberService;
import com.wanyang.service.UserContext;
import com.wanyang.vo.ApiResult;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import javax.servlet.FilterConfig;
import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

@Slf4j
@Component
public class JwtFilter implements Filter {
    @Autowired
    private IgnoreUrlsConfig ignoreUrlsConfig;
    @Autowired
    private JwtTokenHelper jwtTokenHelper;
    @Autowired
    private MemberService memberService;
    @Autowired
    protected ObjectMapper objectMapper;


    public JwtFilter() {
    }

    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
    }

    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain)
            throws IOException, ServletException {
        try {
            doFilterInner(servletRequest, servletResponse, filterChain);
        } catch (Exception ex) {
            log.error(ex.getMessage(), ex);

            HttpServletResponse response = (HttpServletResponse) servletResponse;
            response.setContentType("application/json;charset=UTF-8");

            if (ex instanceof ApiException) {

                objectMapper.writeValue(response.getWriter(), ApiResult.error((ApiException) ex));
            } else {
                objectMapper.writeValue(response.getWriter(), ApiResult.error(500, null, ex.getMessage()));
            }

        }
    }

    private void doFilterInner(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        HttpServletRequest request = (HttpServletRequest) servletRequest;

        String token = request.getHeader("Authorization");

        if (StringUtils.isNotBlank(token)) {
            if (jwtTokenHelper.isTokenExpired(token)) {
                throw new ApiException("token expired", 403);
            }

            Integer memberId = jwtTokenHelper.getUserIdFromToken(token);

            MemberBO memberBO = memberService.getMemberBO(memberId);

            if (memberBO == null) {
                throw new ApiException("invalid token", 403);
            }

            afterDoFilter(memberBO, servletRequest, servletResponse, filterChain);

        } else {
            if (ignoreUrlsConfig.isAllow(request.getRequestURI())) {
                afterDoFilter(null, servletRequest, servletResponse, filterChain);
            } else {
                throw new ApiException("token is null", 403);

            }
        }
    }


    private void afterDoFilter(MemberBO memberBO, ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain)
            throws IOException, ServletException {
        try {
            if (memberBO != null)
                UserContext.set(memberBO);

            filterChain.doFilter(servletRequest,servletResponse);

        } finally {
            if (memberBO != null)
                UserContext.remove();
        }

    }

    @Override
    public void destroy() {

    }
}
